﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;

using $safeprojectname$.Settings;

namespace $safeprojectname$
{
    /// <summary>
    ///     Provides the 'Configuration' based on the Project.config file
    /// </summary>
    public class Global
    {
        #region memebers
        static readonly Global Instance;
        IBaseSettings _defaultSettings;
        IBaseSettingsProvider _provider;
        #endregion memebers

        #region constructor
        /// <summary>
        ///     Singleton isntantiation
        /// </summary>
        static Global()
        {
            Instance = new Global();
        }

        /// <summary>
        ///     Initialize infrastructure for settings reading
        /// </summary>
        protected Global()
        {
            Initialize();
        }
        #endregion constructor

        #region public IBaseSettings
        /// <summary>
        ///     Global application Settings
        /// </summary>
        public static IBaseSettings Settings
        {
            get
            {
                return Instance._provider.Is()
                    ? Instance._provider.BaseSettings
                    : Instance._defaultSettings;
            }
        }
        #endregion public IBaseSettings

        #region public path
        /// <summary>
        ///     Assembles Absolute path based on current context
        ///     to provided relative path
        /// </summary>
        /// <param name = "path"></param>
        /// <returns></returns>
        public static string CreateAbsolutePath(string path)
        {
            if (Instance._provider.IsNull())
            {
                return DefaultAbsolutePath(path);
            }
            return Instance._provider.CreateAbsolutePath(path);
        }

        /// <summary>
        ///     Creates the full path to the 'App_Data' folder. This is the default expected implementation.
        ///     For other purposes (Batch, Tests) target more suitable folder in your implementing IBaseSettingsProvider
        /// </summary>
        /// <param name = "fileName">file name like "file.xml" (with extension)</param>
        /// <returns>The full path to the App_Data folder file</returns>
        public static string CreateAppDataPath(string fileName)
        {
            return Instance._provider.IsNull()
                ? DefaultAppDataPath(fileName)
                : Instance._provider.CreateAppDataPath(fileName);
        }

        public static string CreateFilePath(string fileNameOrPath)
        {
            return Instance._provider.IsNull()
                ? DefaultFilePath(fileNameOrPath)
                : Instance._provider.DefaultFilePath(fileNameOrPath);
        }

        #region private default Path
        /// <summary>
        ///     Default absolute path generator for files like .config etc.
        /// </summary>
        /// <param name = "path"></param>
        /// <returns></returns>
        static string DefaultAbsolutePath(string path)
        {
            var target = path.Replace('/', '\\');
            if (target.StartsWith("\\", StringComparison.Ordinal))
            {
                target = target.Remove(0, 1);
            }
            return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, target);
        }

        /// <summary>
        ///     Default path generator for App_Data folder
        /// </summary>
        /// <param name = "fileName"></param>
        /// <returns></returns>
        static string DefaultAppDataPath(string fileName)
        {
            Contract.Requires(!fileName.Contains('\\') && !fileName.Contains('/'),
                @" parameter fileName cannot contain '/' or '\' ");
            var target = @"App_Data\" + fileName;
            return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, target);
        }

        static string DefaultFilePath(string fileNameOrPath)
        {
            if (!fileNameOrPath.Contains('\\')
                && !fileNameOrPath.Contains('/'))
            {
                return DefaultAppDataPath(fileNameOrPath);
            }
            return Path.GetFullPath(fileNameOrPath);
        }
        #endregion private default Path

        #endregion public path

        /// <summary>
        ///     Returns the underlying IBaseSettingsProvider
        ///     'System.Data.Common.DbCommand NewDbCommand()'
        ///     or null if not provided;
        ///     This is essential for ProjectCore.Data layer, DbSession management.
        ///     The IBaseSettingsProvider is responsible for setting the right type (e.g. Sql or Oracle)
        ///     commonly used on the Project data layer (e.g. for stored procedure handling)
        /// </summary>
        /// <returns></returns>
        public static IDbCommand NewDbCommand()
        {
            if (Instance._provider.Is())
            {
                return Instance._provider.NewDbCommand();
            }
            return null;
        }

        #region protected Provider
        protected static IBaseSettingsProvider BaseProvider
        {
            get { return Instance._provider; }
        }
        #endregion protected Provider

        #region init
        /// <summary>
        ///     IBaseSettingsProvider is instantiated
        /// </summary>
        void Initialize()
        {
            var providerTypeName = ConfigurationManager.AppSettings["ProjectSettingsProvider"];
            if (providerTypeName.Is())
            {
                var targetType = Type.GetType(providerTypeName);
                if (targetType.Is())
                {
                    _provider = Activator.CreateInstance(targetType) as IBaseSettingsProvider;
                    if (_provider.Is())
                    {
                        return;
                    }
                }
            }
            _defaultSettings = new BaseSettings();
        }
        #endregion init
    }
}